/*
 * luaRcallback.h
 */

#ifndef LUA_R_CALLBACK_H_
#define LUA_R_CALLBACK_H_

#include "luaR.h"

/*
 * All-purpose enum for storing Lua values.
 */
union luaR_value {
    int boolean;
    double number;
    char* string;
    int nil; /* actual type and value don't matter here */
};

/*
 * Enum containing the available Lua types.
 */
enum luaR_types {
    luaR_boolean,
    luaR_number,
    luaR_string,
    luaR_nil
};

/*
 * Available types for Lua->C argument passing interface:
 * boolean (returned as int, 0 = false and 1 = true)
 * number (returned as double)
 * string (returned as C-style string)
 * nil (if the type cannot be resolved to any of the above)
 */
struct lua_arg_list {
    enum luaR_types type; /* type flag */
    union luaR_value value;
    struct lua_arg_list* next;
};

/*
 * Registers the given C function as a Lua function with the given package name
 * and function name.
 */
int luaR_callback_register( const char *pkg_name, const char *fn_name,
    void (*fn)(int, struct lua_arg_list*) );

/*
 * The Lua hook to C functions registered through luaR_callback_register().
 * When a C callback is registered, it is given a function ID and a Lua function
 * which calls this callback with the given arguments and the function ID used
 * to create the Lua function. The arguments are converted into a Lua arg list
 * struct, and the C callback is called with the newly created arg list.
 */
int luaR_callback( lua_State *L );

/*
 * Frees the given arg list, freeing the memory of every entity in the list.
 */
int luaR_free_arg_list( struct lua_arg_list *list );

/*
 * Frees the given arg.
 */
int luaR_free_arg( struct lua_arg_list *list );

/*
 * Takes a Lua arg list and attempts to set the given int (passed as a pointer)
 * to the boolean value the first arg on the list represents. This function
 * will fail if the first arg is not a boolean.
 * Returns the next element in the arg list after freeing the first arg.
 */
struct lua_arg_list * luaR_arg_getboolean( struct lua_arg_list *list, int *value );

/*
 * Takes a Lua arg list and attempts to set the given double (passed as a
 * pointer) to the number value the first arg on the list represents. This
 * function will fail if the first arg is not a number.
 * Returns the next element in the arg list after freeing the first arg.
 */
struct lua_arg_list * luaR_arg_getnumber( struct lua_arg_list *list, double *value );

/*
 * Takes a Lua arg list and attempts to set the given integer (passed as a
 * pointer) to the number value the first arg on the list represents. This
 * function will fail if the first arg is not a number.
 * Returns the next element in the arg list after freeing the first arg.
 */
struct lua_arg_list * luaR_arg_getinteger( struct lua_arg_list *list, int *value );

/*
 * Takes a Lua arg list and attempts to set the given char array (passed as a
 * pointer) to the string value the first arg on the list represents. This
 * function will fail if the first arg is not a string.
 * Returns the next element in the arg list after freeing the first arg.
 */
struct lua_arg_list * luaR_arg_getstring( struct lua_arg_list *list, const char **value );

/*
 * Pushes the given integer onto the Lua stack to be returned.
 * Will fail if this function is not called within a call to luaR_callback.
 */
void luaR_arg_pushinteger( int value );

/*
 * Initializes the Lua callback interface.
 * This should only be called once!
 */
int luaR_callback_initialize();

#endif
